package org.amphiprion.myquickrules.screen;

import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import org.amphiprion.myquickrules.dao.MainRuleDao;
import org.amphiprion.myquickrules.entity.Game;
import org.amphiprion.myquickrules.entity.MainRule;
import org.amphiprion.myquickrules.entity.Overview;
import org.amphiprion.myquickrules.entity.Phase;
import org.amphiprion.myquickrules.util.ApplicationConstants;

//import android.R;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Picture;
import android.os.Environment;
import android.util.Log;
import android.webkit.WebView;
import android.webkit.WebView.PictureListener;


public class GameRulesScreenHtml extends GameRulesScreen {

	// Base url for images
	String baseUrl = null;

	class CacheBitmap
	{
		// cached bitmap
		Bitmap cache = null;

		private String lng = Locale.getDefault().getLanguage();
		
		/**
		 * @param phase to draw in cache
		 */
		public void createCache(String html, String background) {
			if (html==null) return;
//			Log.d("CacheBitmap","constructor");
			WebView phaseView = new WebView(getContext());
			phaseView.setBackgroundColor(Color.TRANSPARENT); // by default, will be replace by bgcolor if needed
			phaseView.layout(0, 0, (int)SCREEN_WIDTH, (int)SCREEN_HEIGHT);
			phaseView.setInitialScale(1);
			phaseView.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY); 
			String summary = drawHeader(html);
			phaseView.loadDataWithBaseURL(baseUrl, summary, "text/html", "utf-8", null);
			
			phaseView.setPictureListener(new PictureListener() {
				public void onNewPicture(WebView view, Picture picture) {
					// if not correct size, skip this drawing
//					if ((SCREEN_WIDTH!=picture.getWidth()) && (SCREEN_HEIGHT!=picture.getHeight())) {
					if ((SCREEN_WIDTH>picture.getWidth()) && (SCREEN_HEIGHT>picture.getHeight())) {
						return;
					}
					Bitmap tmpcache = 
							Bitmap.createBitmap( picture.getWidth(), picture.getHeight(), Bitmap.Config.ARGB_8888);
					Canvas c = new Canvas( tmpcache );
					picture.draw( c );
					if (cache!=null) {
						destroyCache();
					}
					cache = tmpcache;
					tmpcache = null;
				}
			});
		}

		/**
		 * @param Create bitmap from phase
		 */
		public CacheBitmap(Phase phase) {
			createCache(phase.html,phase.backgroundName);
		}

		/**
		 * @param Create bitmap from overview
		 */
		public CacheBitmap(Overview overview) {
			createCache(overview.html,overview.backgroundName);
		}

		private String drawHeader(String html) {
			// if end </head> tag is found, add just before
			if (html.indexOf("</head>")>=0) {
				html = html.replace("</head>",drawMeta()+"</head>");
				html = html.replace("</head>",drawLangStyle()+"</head>");
			} else { // if no tag head, add it
				html = "<head>"
						+ drawMeta()
						+ drawLangStyle()
					 + "</head>"
					 + html;
			}
			// TODO Add <head ... /> tag parsing
			return html;
		}

		private String drawMeta() {
			return "<meta name='viewport' content='initial-scale=1, target-densitydpi=device-dpi,  minimum-scale=1.0, maximum-scale=1.0, user-scalable=no, width=device-width'/>\n";
		}
		
		private String drawLangStyle() {
			String result = "<style type='text/css'>\n";
			// all language are not visible,
			// text without lang attribute are always visible
			result += "  [lang] { visibility:hidden; }\n";
			// check for language
			if ((lng!=null) && (lng!="")) {
				// set this language visible
				result += "  [lang='" + lng + "'] { visibility:visible; }\n";
			}
			result += "</style>\n";
			return result;
		}
		
		private void destroyCache() {
			if (cache!=null) {
				Bitmap tmpcache = cache;
				cache = null;
				Log.d("CacheBitmap","recylcle");
				tmpcache.recycle();
			}
		}

		public void onDestroy() {
			destroyCache();
		}
	}

	Map<Phase,CacheBitmap> cachePhaseBitmaps = new HashMap<Phase,CacheBitmap>();
	CacheBitmap cacheOverviewBitmap = null;

	public GameRulesScreenHtml(Context context, Game game) {
		this(context, MainRuleDao.getInstance().getMainRule(game.getId()));
	}
	
	public GameRulesScreenHtml(Context context, MainRule mainRule) {
		super(context,mainRule);
		// get base data (images) files dir
		baseUrl = "file://" + Environment.getExternalStorageDirectory()
				+ "/" + ApplicationConstants.DIRECTORY
				+ "/" + mainRule.id + '/'; 
		// create caches
		for (Phase phase: mainRule.getPhases()) {
			CacheBitmap cachePhaseBitmap = new CacheBitmap(phase);
			cachePhaseBitmaps.put(phase,cachePhaseBitmap);
		}
//		Log.d("CacheBitmaps","size: " + cachePhaseBitmaps.size());
		if (mainRule.getOverview()!=null) {
			cacheOverviewBitmap = new CacheBitmap(mainRule.getOverview());
		}
	}

	public void onDestroy() {
		Log.d("GameRulesScreenHtml","dispose");
		for (Map.Entry<Phase,CacheBitmap> cache: cachePhaseBitmaps.entrySet()) {
			cache.getValue().onDestroy();
		}
		cachePhaseBitmaps = null;
		cacheOverviewBitmap = null;
		super.onDestroy();
	}
	
	@Override
	void drawPhase(Canvas canvas, Phase phase, float offset) {
		boolean drawed = false;
		CacheBitmap cachePhaseBitmap = cachePhaseBitmaps.get(phase);
		if (cachePhaseBitmap!=null) {
			// cache is already asked
			if (cachePhaseBitmap.cache!=null) {
				// cache is done, draw it
				drawImage(canvas, cachePhaseBitmap.cache, offset, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
				drawed = true;
			}
		}
		// if cache is build, use background to temporize !
		if (!drawed) {
			drawImage(canvas, phase.bitmap, SCREEN_WIDTH / 2 + offset, SCREEN_HEIGHT / 2, 1.0f);
		}
	}

	@Override
	void drawOverview(Canvas canvas, Overview overview, float offset) {
		if (cacheOverviewBitmap!=null) {
			drawImage(canvas, cacheOverviewBitmap.cache, 0, offset, SCREEN_WIDTH, SCREEN_HEIGHT);
		}
	}
}
